<template>
  <div class="resource-container">
    <div class="header">
      <el-checkbox
        v-model="checkAll"
        :indeterminate="isIndeterminate"
        @change="handleCheckAllChange"
        >{{ resource.name }}</el-checkbox
      >
    </div>
    <div class="body">
      <el-row>
        <el-col
          :span="8"
          v-for="item in children"
          :key="item.id"
          style="margin: 4px 0px"
        >
          <el-checkbox
            :label="item.name"
            :value="item.selected"
            :key="item.id"
            @change="handleCheckedItemsChange($event, item)"
            >{{ item.name }}</el-checkbox
          >
        </el-col>
      </el-row>
    </div>
  </div>
</template>

<script lang="ts">
import Vue from 'vue'
type ResourceItemSelect = FromServer.ResourceItem & { selected: boolean };
function handleSelected (ids: number[], selectedIds: number[], selected = true) {
  const set = new Set(ids)
  if (selected) {
    selectedIds.forEach((id) => {
      set.add(id)
    })
    return Array.from(set)
  } else {
    selectedIds.forEach((id) => {
      set.delete(id)
    })
    return Array.from(set)
  }
}
export default Vue.extend({
  name: 'ResourceItem',

  props: {
    resource: {
      type: Object,
      required: true
    },
    value: {
      type: Array,
      required: true
    }
  },

  data () {
    return {
      checkAll: false
    }
  },

  computed: {
    children () {
      if (!this.resource.children) return []
      return this.resource.children.map((item: ResourceItemSelect) => {
        return {
          ...item,
          selected: this.value.includes(item.id)
        }
      })
    },
    checkedLength () {
      const vm = (this as {
        children: ResourceItemSelect[]
      })
      return vm.children.filter(item => item.selected).length
    },
    isIndeterminate () {
      const vm = (this as {
        checkAll: boolean
        children: ResourceItemSelect[]
      })
      return !vm.checkAll && vm.children.some(item => item.selected)
    }
  },

  watch: {
    value () {
      if (this.children.length === 0) {
        this.checkAll = false
      } else {
        this.checkAll = !this.children.some((item: ResourceItemSelect) => !item.selected)
      }
    }
  },

  methods: {
    handleCheckAllChange (val: boolean) {
      if (val) {
        if (this.resource.children) {
          const selected = handleSelected(
          this.value as number[],
          this.resource.children.map(
            (item: FromServer.ResourceItem) => item.id
          ),
          true
          )
          this.$emit('input', selected)
        }
        this.checkAll = true
      } else {
        if (this.resource.children) {
          const selected = handleSelected(
          this.value as number[],
          this.resource.children.map(
            (item: FromServer.ResourceItem) => item.id
          ),
          false
          )
          this.$emit('input', selected)
        }
        this.checkAll = false
      }
    },
    handleCheckedItemsChange (value: boolean, item: FromServer.ResourceItem) {
      if (value) {
        const selected = handleSelected(
          this.value as number[],
          [item.id],
          true
        )
        this.$emit('input', selected)
        this.checkAll = (this.checkedLength + 1) === this.children.length
      } else {
        const selected = handleSelected(
          this.value as number[],
          [item.id],
          false
        )
        this.$emit('input', selected)
        this.checkAll = false
      }
    }
  }
})
</script>

<style lang="scss" scoped>
.resource-container {
  width: 100%;
  border-top: 1px solid #dcdfe6;

  .header {
    background: rgb(242, 246, 252);
    padding: 20px;
    border-left: 1px solid #dcdfe6;
    border-right: 1px solid #dcdfe6;
    border-bottom: 1px solid #dcdfe6;
  }

  .body {
    padding: 20px;
    border-left: 1px solid #dcdfe6;
    border-right: 1px solid #dcdfe6;
    border-bottom: 1px solid #dcdfe6;
  }
}
</style>
